<template>
  <div class="about">
    <h3>{{msg}}</h3>
    <div ref="captcha" v-show="showCaptcha"></div>
    <button @click="connectWs">Connect</button>
    <button @click="stopWs">Disconnect</button>
    <button @click="callAPI">Call API</button>
    <div ref="measureDiv"></div>
    <canvas ref="canvasRef" class="canv" @click="onClick"></canvas>
</div>
</template>
<style>
.border {
      border: 1px solid aqua;
} 
.canv {
  background-color: white;
  visibility: visible;
}
/* @media (min-width: 1024px) {
  .about {
    min-height: 100vh;
    display: flex;
    align-items: center;
  }
} */
</style>

<script setup lang="ts">
  import { ref, onMounted, onUnmounted } from "vue"
  import type { Obs } from "@/gutypes"
  import axios from 'axios'
  import { useChallengeV2 } from 'vue-recaptcha'


  async function callAPI() {
    const response = "hello api1"
    const r = await axios.post('/ws/recaptcha/validate', {response})
    console.log('VER',r)
  }

  let showCaptcha = ref<boolean>(true)
  const {root: captcha, onVerify} = useChallengeV2({options: {}})
  onVerify( async (response) => 
    {
      const r = await axios.post('/ws/recaptcha/validate', {response})
      console.log('VER',r)
      if (r.data.valid) {
        showCaptcha.value = false
      }
      connectWs()
      getWsIssue()
    })

  const canvasRef = ref<HTMLCanvasElement | null>(null);
  const measureDiv = ref<HTMLDivElement | null>(null);

  let obs: Obs[] = [];  
  let timeout = 0;
  let drawTimeout = 0;
  let lastDrawTime = new Date();
  let ws: WebSocket | null = null;
  let count = 0;

  let mouseX = 0, mouseY = 0, mouseR = 0;

  const msg = ref("GET-ing...");

  async function getWsIssue() {
    const res = await axios.get('/ws/issue');
    msg.value = res.data;
  }

  function onClick(e: MouseEvent) {
    const pt = getMousePos(canvasRef.value!, e);
    mouseX = pt.x; 
    mouseY = pt.y;
    mouseR = 0;
    drawMouseClick(40);
  }

  function drawMouseClick(radius: number, i=3){
    const canv = canvasRef.value;
    if (!canv)
      return;    
    circle(canv, i);
    mouseR = i;
    if (i < radius)
      setTimeout(() => drawMouseClick(radius, i + 1), 10);
    else
      mouseR = 0;
  }

  function circle(canv: HTMLCanvasElement, r: number) {
    const ctx = canv.getContext("2d")!;
    ctx.lineWidth = 3;
    ctx.strokeStyle = "green";
    ctx.beginPath();
    ctx.arc(mouseX, mouseY, r, 0, 2 * Math.PI);
    ctx.stroke();

    ctx.lineWidth = 2;
    ctx.strokeStyle = "magenta";
    ctx.beginPath();
    ctx.arc(mouseX, mouseY, r*0.2, 0, 2 * Math.PI);
    ctx.stroke();    
  }

  function stopWs() {
    if (ws?.readyState == WebSocket.OPEN) {
      ws.send('stop');
    }
  }

  function connectWs() {
    let wsproto = window.location.protocol.replace('http', 'ws');
    ws?.close();    
    ws = new WebSocket(`${wsproto}//${window.location.hostname}/ws/sin`);
    ws.onmessage = function(event) {
        var json = JSON.parse(event.data);
        obs.push(json);
        ++count;
        if (obs.length > 1000) {
          obs = obs.slice(-900);
        }
        let t = drawTimeout;
        if (t) {
          window.clearTimeout(t);
        }
        if (new Date().getTime() - lastDrawTime.getTime() > 1000) {
          draw();
        }
        else {
          drawTimeout = window.setTimeout(draw);
        }
    };      
  }

  onUnmounted(() => {
    window.clearTimeout(timeout);
    if (ws != null) {
      ws.close();
      ws = null;
    }
  });

  onMounted(async () => {
    connectWs();
    await getWsIssue();
  });

  function drawObs(ctx: CanvasRenderingContext2D, o, y) {
      ctx.beginPath();

      ctx.moveTo(0,  y);
      ctx.lineTo(o.x, y);
      ctx.lineTo(o.x, y+1);
      ctx.lineTo(0, y+1);

      ctx.strokeStyle = ctx.fillStyle = "blue";
      ctx.closePath();
      //rtx.fill();
      ctx.stroke();

      if (o.y !== undefined) {
        ctx.beginPath();
        ctx.moveTo(0, y+1);
        ctx.lineTo(o.y , y+1);
        ctx.lineTo(o.y , y+2);
        ctx.lineTo(0 , y+2);
        ctx.strokeStyle = ctx.fillStyle = "red";
        ctx.closePath();
        //rtx.fill();
        ctx.stroke();;
      }
      return 2; // 2 lines drawn
  }

  function drawObs2(ctx: CanvasRenderingContext2D, o, y) {
      ctx.fillStyle = "blue";
      ctx.fillRect(0, y, o.x, 1);
      if (o.y) {
        ctx.fillStyle = "red";
        ctx.fillRect(0, y, o.y, 1);
      }
      return 1
  }

  function draw() {
    const canv = canvasRef.value;
    if (!canv)
      return;
    canv.width = measureDiv.value!.clientWidth;
    canv.height = window.innerHeight - 50;
    drawTimeout = 0;
    const ctx = canv.getContext("2d")!; 

    ctx.clearRect(0, 0, canv.width, canv.height);
    ctx.lineWidth = 1
    // rtx.globalCompositeOperation = "screen";
    
    let line = 0;
    for (let i=obs.length-1; i>=0; --i) {
      line += drawObs(ctx, obs[i], line);
    }

    ctx.fillStyle = "gray";
    ctx.font = "16px serif";
    ctx.fillText(`${obs.length} ${count}`, canv.width / 2, 30);

    if (mouseR)
      circle(canv, mouseR);
    lastDrawTime = new Date();
    // console.log("drawn elements", obs.length, lastDrawTime);
  }

  function getMousePos(canvas: HTMLCanvasElement, evt) {
    var rect = canvas.getBoundingClientRect(), // abs. size of element
      scaleX = canvas.width / rect.width,    // relationship bitmap vs. element for x
      scaleY = canvas.height / rect.height;  // relationship bitmap vs. element for y

    return {
      x: (evt.clientX - rect.left) * scaleX,   // scale mouse coordinates after they have
      y: (evt.clientY - rect.top) * scaleY     // been adjusted to be relative to element
    }
}  
  
</script>
